iT邦幫忙

2023 iThome 鐵人賽

DAY 16
1
AI & Data

如何借助 dbt 優化當代資料倉儲及資料工程師的水肥之路分享系列 第 16

dbt snapshot 介紹 - 怎麼設定? 各種 snapshot 策略有什麼差異? 有什麼要注意的?

  • 分享至 

  • xImage
  •  

dbt snapshot 介紹 - 怎麼設定? 各種 snapshot 策略有什麼差異? 有什麼要注意的?

dbt snapshots 是什麼?

dbt snapshots 是 dbt 提供的一種備份機制,記錄隨時間變化的 table 情況

為何要用 snapshot?

就 migo data 團隊使用 snapshot 有兩個目的:

  1. 備份以備不時之需,若有資料是會被 update 的,哪天資料錯誤想要復原就需要 snapshot
  2. 有些 table 邏輯是根據過往資料而更新,若使用 snapshot 就比較方便讀取舊資料,否則會有自我 table 更新的情況發生

dbt 使用的備份機制

dbt 的 snapshot 機制為來源 table type-2 Slowly Changing Dimensions (或稱 SCDs)*,用於識別 table 中的 row 如何隨時間變化。 *SCD 的定義

如何使用

  1. (不一定要做)在 dbt_project.yml 的 snapshot-paths 定義你的 snapshot sql 語法的路徑位置(預設在 /snapshot 下,若不變更就不用這步)
  2. 若要將 snapshot 加入你的專案,請在你的 snapshots 目錄中創建一個 .sql 檔案擴展名的檔案,例如 snapshots/orders.sql

以下寫在 snapshot sql 檔內,以 member_snapshot.sql 為例


  1. 定義 snapshot table name
  2. 定義 snapshot 的 config 設定
  3. 定義你的 snapshot query 語法

範例

---1---
{% snapshot member_snapshot %}  
------2------
{{
    config(
      target_database='migocorp-2103',
      target_schema='snapshots',
			unique_key='MemberID',
      strategy='timestamp',
      updated_at='UpdateDate'
    )
}}
----3-----
select * from {{ source('jaffle_shop', 'orders') }}

{% endsnapshot %}

config 如何設定

target_database, target_schema 不特別說,就是你的 snapshot 要放的 database 和 schema 地方以下介紹其他三項:

  • strategy:你一開始要決定要用什麼 snapshot 策略

    最常用的是 timestamp, check 兩個

    • timestamp
      timestamp 策略使用 updated_at 欄位來判斷一行資料是否有變動。如果某 row 資料的 updated_at 欄位比上次執行 snapshot 的時間更晚,dbt 將會使舊的記錄失效並記錄新的資料。如果時間戳沒有變化,那麼 dbt 將不會採取任何行動。如果你的 table 有 updated_at 的欄位記錄資料更新時間,這是 dbt snapshot 優先建議的策略
    • check
      對於沒有可靠 updated_at 欄位的 table,dbt 建議使用 check 策略。這種策略是透過比較check_cols 欄位資料有無變動來判斷。如果這些欄位中的任何一個有變化,那麼 dbt 將會使舊的記錄失效並記錄新的資料。如果欄位值相同,那麼 dbt 將不會採取任何行動
      以下為 check 策略範例:
{% snapshot orders_snapshot_check %}

    {{
        config(
          target_schema='snapshots',
          strategy='check',
          unique_key='id',
          check_cols=['status', 'is_cancelled'],
        )
    }}

    select * from {{ source('jaffle_shop', 'orders') }}

{% endsnapshot %}
  • unique_key
    這是 dbt 去比對某一筆資料是否有變動的 key 值,此欄位必須是唯一值,若沒有 key 值也可以用組合欄位當 key
{% snapshot transaction_items_snapshot %}

    {{
        config(
          unique_key="transaction_id||'-'||line_item_id",
          ...
        )
    }}

select
    transaction_id||'-'||line_item_id as id,
    *
from {{ source('erp', 'transactions') }}

{% endsnapshot %}
  • updated_at

    使用 timestamp 策略則需要填此項目,dbt 用此時間欄位判斷資料無更新以記錄資料

  • check_cols

    用 check 策略則需要填此項目,只要填入欄位值與原本有差異都會紀錄

snapshot 的 結果是什麼?

你的 table 會多4個欄位

欄位 解釋 用法
dbt_valid_from snapshot row 被 insert 的時間 透過 dbt_valid_from 看該欄位的不同時間版本
dbt_valid_to 若該 row 已有新紀錄,則舊的 row 變成無效的時間 可以當作 row 的有效期限日,假如是最新的 row 則是 null.
dbt_scd_id 每個 snapshot 紀錄的 unique key dbt 內部邏輯判斷使用
dbt_updated_at 該 row 更新時間 dbt 內部邏輯判斷使用

config 還有其他地方可以設定

若你有很多 table 須設定 snapshot,在每個 model 內設定 config 是比較難管理的,因此你可以參考過去說的 dbt 架構設計,在 dbt_project.yml 管理每個 table snapshot 的設定,如下範例

dbt_project.yml

snapshots:
  migocorp:
	datamart:
      Member_snapshot:
        +unique_key: MemberID
        +strategy: timestamp
        +updated_at: UpdateDate

注意事項

  1. 若你的其他 model 要抓取 snapshot table 的資料,請用  ref ,而不是用 source 喔!
-- models/changed_orders.sql
select * from {{ ref('orders_snapshot') }}
  1. snapshot 來源 table 欄位有變動怎麼處理

    • 增加欄位: dbt 會在 snapshot table 增加欄位
    • 刪除欄位或欄位型態異動: dbt 的 snaptshot table 都不會變動
  2. key 值有重複會發生什麼事?

    若你的 key 值有重複,可能導致結果誤差,且 dbt 不會幫你檢查。因此建議來源 table 多做 unique 檢查

  3. 如果你的 snapshot 來源 table 刪除 row, dbt 怎麼處理?

    dbt 預設刪掉的 row 是正常的,你若要挑出來需設定 invalidate_hard_deletes=True,則 dbt 會把 snapshot table 的 dbt_valid_to 欄位設為現在時間

越寫越覺得 dbt snapshot 的水很深,還有其他注意事項請來官方查看


上一篇
如何使用 dbt incremental 增量更新你的資料?
下一篇
dbt Core 基礎部署架構
系列文
如何借助 dbt 優化當代資料倉儲及資料工程師的水肥之路分享30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言